《九浅一深node.js》Book Note

更新中。。。

模块机制

  • CommonJS希望JS可以在任何地方运行。
  • exports是唯一导出的接口,在模块中有一个module对象,代表自己,而exports就是module的属性。
  • require允许不包含扩展名,会按照.js, .node, .json尝试。
  • 同步配合缓存,可以大幅度缓解Node单线程阻塞调用的缺陷。
  • 18 ~

异步I/O

  • I/O disctributed I/O is pretty expensive
  • The cost of multi-thread when you create thread, and switch between them is expensive.
  • Asynchronous I/O
1
2
3
4
5
6
7
8
9
App OS
I/O call------> process request
/||
other call ||
||
||
||/
callback process done
  • repeatly to call I/O is 轮询
  • 55 ~

Asynchronous Programming

Continuation Passing Style

1
2
3
function foo(x, bar) {
return bar(x);
}

业务重点由返回值转移到了毁掉函数中。

  • 偏函数
1
2
3
4
5
6
7
8
9
10
var toString = Object.prototype.toString;
var isString = function(obj) {
return toString.call(obj) == '[object string]';
};
var isType = function(type) {
return function(obj) {
return toString.call(obj) == '[object' + type + ']';
};
};
  • 雪崩就是高访问并发的时候大量请求同时涌入数据库。
    用事件队列解决
1
2
3
4
5
6
7
8
9
10
11
12
13
var proxy = new events.EventEmitter();
var status = "ready";
var select = function(callback) {
proxy.once("selected", callback);
if (status == "ready") {
status = "pending";
db.select("SQL", function(results) {
proxy.emits("selected", results);
status = "ready";
});
}
};
// 保证相同的SQL语句从开始到结束永远只有一次,Node单线程执行所以无需担心状态同步问题。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
var count = 0;
var results = {};
var done = unction(key, value) {
results[key] = value;
count++;
if (count === 3) {
render(results);
}
};
fs.readFile(template_path, "utf8", function(err, template) {
done("template", template);
});
db.query(sql, function(err, data) {
done("data", data);
});
/* L10n.get
Synchronous method for retrieving localization strings from app's resources. This function should
be used only when direct manipulation on the strings is needed (etc. date/time formatting) and in
all other UI related cases should be replaced with DOM attributes setting or L10n.setAttributes().
This method has also potential to generate race conditions so a developer has to make sure that any
code that uses this method is not fired before l10n resources are loaded using L10n.once() or L10n.
ready().*/
l10.get(function(err, resources) {
done("resources", resources);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
// 烧饼(哨兵)变量和偏函数结合
var after = function(times, callback) {
var count = 0, resutls = {};
return function(key, value) {
results[key] = value;
counts++;
if (count === times) {
callback(results);
}
};
};
var done = after(times, render);
1
2
3
4
5
6
7
8
9
10
// 多对一的收敛和事件订阅/发布
var emitter = new events.Emitter();
var done = after(times, render);
emitter.on("done", done);
emitter.on("done", other);
fs.readFile(template_path, "utf8", function(err, template) {
emitter.emit("done", "template", template);
})
  • 74 ~

构建Web应用